#include "ServerApplication.h"
#include <XnccType.h>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <memory>
#include <sstream>
#include "ConfMgr.h"
#include "EventEngine.h"
#include "Logger.h"
#include "Manager.h"
#include "PlatLogger.h"
#include "Util.h"

namespace xncc {
xncc::Logger plat_logger;
namespace user {

    static std::vector<std::shared_ptr<EventEngine>> engList_;
    static std::set<types::engine_id_t>              idList_;
    static std::string                               confFile_;
    static std::string                               confStr_;
    static bool                                      serverApplicationInited = false;
    static bool                                      serverRun               = false;

    static void applicationInit()
    {
        if (serverApplicationInited) {
            return;
        }
        config::ConfMgr cmgr;
        int             ret = 0;
        if (!confFile_.empty()) {
            ret = cmgr.loadCfgFile(confFile_);
        }
        else if (!confStr_.empty()) {
            ret = cmgr.loadCfgString(confStr_);
        }
        else {
            ret = cmgr.loadCfgFile(confFile_);
        }
        if (ret != 0) {
            throw shared::logic_exception("conf file: conf.json open failed");
        }
        auto errCfg = cmgr.init();
        if (errCfg.first != 0) {
            throw shared::logic_exception("conf file init failed " + errCfg.second);
        }
        PLAT_LOG.Set(cmgr.Cfg().LogInfo.LogName, cmgr.Cfg().LogInfo.LogPath, cmgr.Cfg().LogInfo.RotateSize,
                     static_cast<LOG_LEVEL>(cmgr.Cfg().LogInfo.LogLevel), cmgr.Cfg().LogInfo.CoreId);
        QUEUE_MGR.init(cmgr);
        const int err = LOOP_MGR.init(cmgr.Cfg());
        if (err != 0) {
            throw shared::logic_exception("loop manager  init failed ");
        }
        serverApplicationInited = true;
    }

    ServerApplication::ServerApplication(const std::string& f, const std::string& cfg)
    {
        confFile_ = f;
        confStr_  = cfg;
        applicationInit();
    }

    ServerApplication::~ServerApplication() = default;

    void ServerApplication::addEventengine(const std::shared_ptr<EventEngine>& engine)
    {
        if (idList_.count(engine->id()) == 0) {
            engList_.push_back(engine);
            idList_.insert(engine->id());
        }
        else {
            std::ostringstream oss;
            oss << "id:" << engine->id() << " exist";
            throw shared::logic_exception(oss.str());
        }
    }

    int ServerApplication::run(int /*argc*/, const char** /*argv*/)
    {
        serverRun = true;
        init();
        if (engList_.empty()) {
            throw shared::logic_exception("engine list empty, server will not start");
        }
        for (const auto& ptr : engList_) {
            ptr->init();
        }
        xncc::Logger::start();
        LOOP_MGR.startAll();
        LOOP_MGR.joinAll();
        return 0;
    }

    void ServerApplication::stop() { LOOP_MGR.stopAll(); }
}  // namespace user
}  // namespace xncc